package lg.minecraft.plugin.pokedex.config;

import com.cobblemon.mod.common.pokemon.Species;
import lg.minecraft.plugin.cobblemoncore.util.PokemonUtil;
import lg.minecraft.plugin.library.config.LGBaseConfig;
import lg.minecraft.plugin.library.item.ItemProperties;
import lg.minecraft.plugin.library.item.builder.DynamicItemBuilder;
import lg.minecraft.plugin.library.item.builder.PlaceholderItemBuilder;
import lg.minecraft.plugin.pokedex.LGPokedex;
import lg.minecraft.plugin.pokedex.item.builder.PokemonRewardItemBuilder;
import lg.minecraft.plugin.pokedex.item.builder.RewardItemBuilder;
import lg.minecraft.plugin.pokedex.reward.RewardStatus;
import org.bukkit.inventory.ItemStack;

import java.util.*;

/**
 * @author langle__
 * @version 1.0
 */
public class GuiItemConfig extends LGBaseConfig {

    public static final GuiItemConfig INSTANCE = new GuiItemConfig();

    private ItemProperties border;
    private ItemProperties back;
    private ItemProperties nullPokemon;

    private PlaceholderItemBuilder nextPage;
    private PlaceholderItemBuilder previousPage;

    private DynamicItemBuilder hideAirPokemon;
    private DynamicItemBuilder hidePokemon;
    private DynamicItemBuilder hideReceivedPokemon;

    private RewardItemBuilder gen1;
    private RewardItemBuilder gen2;
    private RewardItemBuilder gen3;
    private RewardItemBuilder gen4;
    private RewardItemBuilder gen5;
    private RewardItemBuilder gen6;
    private RewardItemBuilder gen7;
    private RewardItemBuilder gen8;
    private RewardItemBuilder gen9;
    private RewardItemBuilder allGen;
    private RewardItemBuilder airPokemon;

    private PokemonRewardItemBuilder pokemon;

    public GuiItemConfig() {
        super(LGPokedex.getInstance(), "guiItem.yml");
        saveDefault();
        load();
    }

    @Override
    public void load() {
        super.load();
        border = getItemProperties("border");
        back = getItemProperties("back");
        nextPage = getPlaceholderItemBuilder("next_page");
        previousPage = getPlaceholderItemBuilder("previous_page");
        hideAirPokemon = getDynamicItemBuilder("hide_air_pokemon");
        hidePokemon = getDynamicItemBuilder("hide_pokemon");
        hideReceivedPokemon = getDynamicItemBuilder("hide_received_pokemon");
        gen1 = getRewardItemBuilder("gen1");
        gen2 = getRewardItemBuilder("gen2");
        gen3 = getRewardItemBuilder("gen3");
        gen4 = getRewardItemBuilder("gen4");
        gen5 = getRewardItemBuilder("gen5");
        gen6 = getRewardItemBuilder("gen6");
        gen7 = getRewardItemBuilder("gen7");
        gen8 = getRewardItemBuilder("gen8");
        gen9 = getRewardItemBuilder("gen9");
        allGen = getRewardItemBuilder("all_gen");
        pokemon = getPokemonRewardItemBuilder("pokemon");
        airPokemon = getRewardItemBuilder("air_pokemon");
        nullPokemon = getItemProperties("null_pokemon");
    }

    public ItemStack getBorder() {
        return border.toItemStack();
    }

    public ItemStack getBack() {
        return back.toItemStack();
    }

    public ItemStack getNextPage(int page, int maxPage) {
        Map<String, String> map = new HashMap<>();
        map.put("page", String.valueOf(page));
        map.put("max_page", String.valueOf(maxPage));
        return nextPage.build(map);
    }

    public ItemStack getPreviousPage(int page, int maxPage) {
        Map<String, String> map = new HashMap<>();
        map.put("page", String.valueOf(page));
        map.put("max_page", String.valueOf(maxPage));
        return previousPage.build(map);
    }

    public ItemStack getHideAirPokemon(boolean b) {
        return hideAirPokemon.build(Collections.emptyMap(), b);
    }

    public ItemStack getHidePokemon(boolean b) {
        return hidePokemon.build(Collections.emptyMap(), b);
    }

    public ItemStack getHideReceivedPokemon(boolean b) {
        return hideReceivedPokemon.build(Collections.emptyMap(), b);
    }

    private ItemStack getGen(int count, boolean receive, int maxCount, int remainingCount, List<String> rewardList, RewardItemBuilder builder) {
        RewardStatus status = receive ? RewardStatus.CLAIMED : remainingCount == 0 ? RewardStatus.QUALIFIED : RewardStatus.NOT_QUALIFIED;
        Map<String, String> map = new HashMap<>();
        map.put("count", String.valueOf(count));
        map.put("max_count", String.valueOf(maxCount));
        map.put("progress_bar", generateProgressBar(calculatePercentage(count, maxCount)));
        map.put("remaining_count", String.valueOf(remainingCount));
        return builder.build(map, status, rewardList);
    }

    public ItemStack getGen1(int count, boolean receive) {
        int maxCount = GenConfig.INSTANCE.getGen1().size();
        int remainingCount = maxCount - count;
        List<String> rewardList = RewardConfig.INSTANCE.getGen1().addLore();
        return getGen(count, receive, maxCount, remainingCount, rewardList, gen1);
    }

    public ItemStack getGen2(int count, boolean receive) {
        int maxCount = GenConfig.INSTANCE.getGen2().size();
        int remainingCount = maxCount - count;
        List<String> rewardList = RewardConfig.INSTANCE.getGen2().addLore();
        return getGen(count, receive, maxCount, remainingCount, rewardList, gen2);
    }

    public ItemStack getGen3(int count, boolean receive) {
        int maxCount = GenConfig.INSTANCE.getGen3().size();
        int remainingCount = maxCount - count;
        List<String> rewardList = RewardConfig.INSTANCE.getGen3().addLore();
        return getGen(count, receive, maxCount, remainingCount, rewardList, gen3);
    }

    public ItemStack getGen4(int count, boolean receive) {
        int maxCount = GenConfig.INSTANCE.getGen4().size();
        int remainingCount = maxCount - count;
        List<String> rewardList = RewardConfig.INSTANCE.getGen4().addLore();
        return getGen(count, receive, maxCount, remainingCount, rewardList, gen4);
    }

    public ItemStack getGen5(int count, boolean receive) {
        int maxCount = GenConfig.INSTANCE.getGen5().size();
        int remainingCount = maxCount - count;
        List<String> rewardList = RewardConfig.INSTANCE.getGen5().addLore();
        return getGen(count, receive, maxCount, remainingCount, rewardList, gen5);
    }

    public ItemStack getGen6(int count, boolean receive) {
        int maxCount = GenConfig.INSTANCE.getGen6().size();
        int remainingCount = maxCount - count;
        List<String> rewardList = RewardConfig.INSTANCE.getGen6().addLore();
        return getGen(count, receive, maxCount, remainingCount, rewardList, gen6);
    }

    public ItemStack getGen7(int count, boolean receive) {
        int maxCount = GenConfig.INSTANCE.getGen7().size();
        int remainingCount = maxCount - count;
        List<String> rewardList = RewardConfig.INSTANCE.getGen7().addLore();
        return getGen(count, receive, maxCount, remainingCount, rewardList, gen7);
    }

    public ItemStack getGen8(int count, boolean receive) {
        int maxCount = GenConfig.INSTANCE.getGen8().size();
        int remainingCount = maxCount - count;
        List<String> rewardList = RewardConfig.INSTANCE.getGen8().addLore();
        return getGen(count, receive, maxCount, remainingCount, rewardList, gen8);
    }

    public ItemStack getGen9(int count, boolean receive) {
        int maxCount = GenConfig.INSTANCE.getGen9().size();
        int remainingCount = maxCount - count;
        List<String> rewardList = RewardConfig.INSTANCE.getGen9().addLore();
        return getGen(count, receive, maxCount, remainingCount, rewardList, gen9);
    }

    public ItemStack getAllGen(int gen1, int gen2, int gen3, int gen4, int gen5, int gen6, int gen7, int gen8, int gen9, int count, boolean receive) {
        int gen1Count = GenConfig.INSTANCE.getGen1().size();
        int gen2Count = GenConfig.INSTANCE.getGen2().size();
        int gen3Count = GenConfig.INSTANCE.getGen3().size();
        int gen4Count = GenConfig.INSTANCE.getGen4().size();
        int gen5Count = GenConfig.INSTANCE.getGen5().size();
        int gen6Count = GenConfig.INSTANCE.getGen6().size();
        int gen7Count = GenConfig.INSTANCE.getGen7().size();
        int gen8Count = GenConfig.INSTANCE.getGen8().size();
        int gen9Count = GenConfig.INSTANCE.getGen9().size();
        int maxCount = GenConfig.INSTANCE.getAllGen().size();
        int remainingCount = maxCount - count;
        List<String> rewardList = RewardConfig.INSTANCE.getAllGen().addLore();
        RewardStatus status = receive ? RewardStatus.CLAIMED : remainingCount == 0 ? RewardStatus.QUALIFIED : RewardStatus.NOT_QUALIFIED;
        List<Entry> entryList = new ArrayList<>();
        entryList.add(new Entry("gen1", gen1, gen1Count));
        entryList.add(new Entry("gen2", gen2, gen2Count));
        entryList.add(new Entry("gen3", gen3, gen3Count));
        entryList.add(new Entry("gen4", gen4, gen4Count));
        entryList.add(new Entry("gen5", gen5, gen5Count));
        entryList.add(new Entry("gen6", gen6, gen6Count));
        entryList.add(new Entry("gen7", gen7, gen7Count));
        entryList.add(new Entry("gen8", gen8, gen8Count));
        entryList.add(new Entry("gen9", gen9, gen9Count));
        Map<String, String> map = new HashMap<>();
        map.put("count", String.valueOf(count));
        map.put("max_count", String.valueOf(maxCount));
        int percentage = calculatePercentage(count, maxCount);
        map.put("percentage", String.valueOf(percentage));
        map.put("progress_bar", generateProgressBar(percentage));
        map.put("remaining_count", String.valueOf(remainingCount));
        for (Entry entry : entryList) {
            map.put(entry.name() + "_count", String.valueOf(entry.count()));
            map.put(entry.name() + "_max_count", String.valueOf(entry.maxCount()));
            map.put(entry.name() + "_percentage", String.valueOf(calculatePercentage(entry.count(), entry.maxCount())));
            map.put(entry.name() + "_qualified", entry.count == entry.maxCount ? "§a✓" : "§7○");
        }
        return allGen.build(map, status, rewardList);
    }

    public ItemStack getPokemon(Species species, RewardConfig.PokemonEntry pokemonReward, boolean receive) {
        Map<String, String> map = new HashMap<>();
        map.put("species", PokemonUtil.getSpeciesName(species));
        map.put("national_pokedex_number", padWithZeros(species.getNationalPokedexNumber()));
        map.put("showdown_id", species.showdownId());
        return pokemon.build(species, map, receive, pokemonReward.addLore());
    }

    public ItemStack getAirPokemon(Species species, RewardConfig.PokemonEntry pokemonReward) {
        Map<String, String> map = new HashMap<>();
        map.put("species", PokemonUtil.getSpeciesName(species));
        map.put("national_pokedex_number", padWithZeros(species.getNationalPokedexNumber()));
        map.put("showdown_id", species.showdownId());
        return airPokemon.build(map, RewardStatus.NOT_QUALIFIED, pokemonReward.addLore());
    }

    public ItemStack getNullPokemon() {
        return nullPokemon.toItemStack();
    }

    private PlaceholderItemBuilder getPlaceholderItemBuilder(String name) {
        return new PlaceholderItemBuilder(getItemProperties(name));
    }

    private DynamicItemBuilder getDynamicItemBuilder(String name) {
        return new DynamicItemBuilder(getItemProperties(name + "-enable"), getItemProperties(name + "-disable"));
    }

    private RewardItemBuilder getRewardItemBuilder(String name) {
        return new RewardItemBuilder(getItemProperties(name + "-not_qualified"), getItemProperties(name + "-qualified"), getItemProperties(name + "-claimed"));
    }

    private PokemonRewardItemBuilder getPokemonRewardItemBuilder(String name) {
        return new PokemonRewardItemBuilder(getItemProperties(name + "-qualified"), getItemProperties(name + "-claimed"));
    }

    /**
     * 生成 Minecraft 风格的进度条字符串。
     * 已完成部分为绿色(§a)，未完成部分为灰色(§7)
     *
     * @param percentage 百分比，范围 0~100
     * @return 格式化后的进度条字符串
     */
    public static String generateProgressBar(int percentage) {
        final int TOTAL_BARS = 20;
        final String FILLED = "█";
        final String UNFILLED = "█";
        final String COLOR_FILLED = "§a";
        final String COLOR_UNFILLED = "§7";

        int filledBars = Math.min(TOTAL_BARS, Math.max(0, percentage * TOTAL_BARS / 100));
        int unfilledBars = TOTAL_BARS - filledBars;

        StringBuilder builder = new StringBuilder();

        if (filledBars > 0) builder.append(COLOR_FILLED).append(FILLED.repeat(filledBars));

        builder.append(COLOR_UNFILLED).append(UNFILLED.repeat(unfilledBars));

        return builder.toString();
    }

    public static int calculatePercentage(double count, double total) {
        return (int) Math.floor(count / total * 100);
    }

    public static String padWithZeros(int number) {
        return String.format("%04d", number);
    }

    public record Entry(String name, int count, int maxCount) {}

}
